package home.contaduria.domain;

import home.contaduria.validation.FieldMatch;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * 
 * @author et0390
 * 
 */
@Entity
@FieldMatch.List({ @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match") })
public class Client extends AbstractEntity<Long> implements UserDetails {

	private static final String FIELDS_SEPARATOR = ";\n";

	private static final long serialVersionUID = -5290604565746320051L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id")
	private Long id;

	@Version
	@Column(name = "version")
	private Integer version;

	@NotBlank
	@Size(min = 1, max = 25)
	@Column(name = "login", nullable = false, unique = true, length = 25)
	private String login;

	@NotBlank
	@Size(max = 25)
	@Column(name = "password", nullable = false, length = 25)
	private String password;

	@NotBlank
	@Size(max = 25)
	@Transient
	private String confirmPassword;

	@NotBlank
	@Column(name = "email", nullable = false, unique = true, length = 50)
	private String email;

	@Column(name = "firstName", length = 25)
	private String firstName;

	@Column(name = "lastName", length = 25)
	private String lastName;

	@Column(name = "state", nullable = false, length = 15)
	@Enumerated(EnumType.STRING)
	private ClientState state;

	@ElementCollection(targetClass = AppRole.class, fetch=FetchType.EAGER)
	@JoinTable(name = "authorities", joinColumns = @JoinColumn(name = "login", referencedColumnName = "login"))
	@Column(name = "role", nullable = false, length = 15)
	@Enumerated(EnumType.STRING)
	private Set<AppRole> roles;

	@Override
    public Long getId() {
		return id;
	}

	@Override
    public void setId(Long id) {
		this.id = id;
	}

	public Integer getVersion() {
		return version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public String getLogin() {
		return login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getConfirmPassword() {
		return confirmPassword;
	}

	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public ClientState getState() {
		return state;
	}

	public void setState(ClientState state) {
		this.state = state;
	}

	public Set<AppRole> getRoles() {
		return roles;
	}

	public void setRoles(Set<AppRole> roles) {
		this.roles = roles;
	}

	@Override
	public Collection<GrantedAuthority> getAuthorities() {
		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		for (GrantedAuthority grantedAuthority : roles) {
			authorities.add(grantedAuthority);
		}
		return authorities;
	}

	@Override
	public String getUsername() {
		return login;
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return state.equals(ClientState.ACTIVE);
	}
	
	@Override
	public String toString() {
		StringBuilder result = new StringBuilder("Client[");
		result.append("id = " + id + FIELDS_SEPARATOR);
		result.append("login = " + login + FIELDS_SEPARATOR);
		result.append("firstName = " + firstName + FIELDS_SEPARATOR);
		result.append("lastName = " + lastName + FIELDS_SEPARATOR);
		result.append("email = " + email + FIELDS_SEPARATOR);
		result.append("state = " + state + FIELDS_SEPARATOR);
		result.append("]");
		return result.toString();
	}

    @Override
    protected String[] declareExcludeFields() {
        return new String[] { "roles" };
    }

}
